﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ValidationFramework.Configuration.Fluent
{
	/// <summary>
	/// A base class for validator configuration. When inherited by consumers they can provide a fluent
	/// interface for configuring thier validators post construction. Consumers must inherit from this class
	/// since it provides the end point for the fluent interface and rule constrcution.
	/// </summary>
	/// <typeparam name="TMember"></typeparam>
	/// <typeparam name="TSpec"></typeparam>
	/// <remarks>Implement IRuleOptions so the consumer can move out of 'validationOption' scope.</remarks>
	public class DefaultSpecificationConfigurationStep<TSpec, TTypeToValidate> : IRuleConfigurationStep where TSpec : ISpecification
	{
		protected TSpec Specification { get; set; }
		private Rule _rule;

		private DefaultSpecificationConfigurationStep()
		{
			// enforce the constructor which also creates a rule
		}

		/// <summary>
		/// Initializes a new instance of validatorOptions.
		/// </summary>
		/// <param name="ruleLocation"></param>
		/// <param name="validator"></param>
		public DefaultSpecificationConfigurationStep(RuleCreationStep<TTypeToValidate> ruleCreationStep, TSpec validator)
		{
			// On constructions create the rule and get a reference to it and its validator.
			// From this point on the fluent config will be modifying the rule in the policy.

			// Note: We create the rule here instead of in the ruleCreationStep so consumers don't have to worry about
			// creating the rule when they create RuleCreationStep extensions.
			_rule = ruleCreationStep.CreateRule(validator);
			Specification = (TSpec)_rule.Specification;
		}


		#region IRuleOptions Members

		public IRuleFailureConfigurationStep OnFailure()
		{
			var options = new RuleConfigurationStep(_rule);
			return options.OnFailure();
		}

		public IRuleConfigurationStep When()
		{
			var options = new RuleConfigurationStep(_rule);
			return options.When();
		}

		public IRuleConfigurationStep Priority(int priorityLevel)
		{
			var options = new RuleConfigurationStep(_rule);
			return options.Priority(priorityLevel);
		}

		#endregion
	}
}
